home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / phantz.arc / PHANT1.Z / PHANT1
Text File  |  1991-06-06  |  61KB  |  2,088 lines

  1.  
  2. : ---------CUT HERE---------
  3. : This is a shar archive.  Extract with sh, not csh.
  4. : The rest of this file will extract:
  5. :  README Makefile main.c include.h phantstruct.h map.c monsters.asc
  6. echo x - README
  7. sed 's/^X//' > README << '!EOR!'
  8. XJune 25, 1986
  9. X
  10. X
  11. XThis is a much modified version of Phantasia.  It is intended to fix
  12. Xall reported bug fixes, enhance the game, and speed up the game.
  13. X
  14. XI have to thank Chris Robertson for many ideas which have made the game
  15. Xfaster, and more user-friendly.  Most of her changes/additions are
  16. Xincorporated in this latest versions, although perhaps not in the exact
  17. Xmanner of her design.  I left out a few items which were not in keeping
  18. Xwith the spirit of the game.  (For example, I didn't like the extra lives
  19. Xand the pausing of the game.  I think it's too easy even WITHOUT that stuff.)
  20. X
  21. XCHANGES:
  22. X
  23. X    - Wormholes have been deleted (I never liked them anyway).
  24. X    - The source code has been greatly enhanced for speed, size, readability,
  25. X      and maintainability.
  26. X      fight.c should no longer cause optimizers to run out of space.
  27. X    - A few loopholes have been tightened to make the game more enjoyable.
  28. X      (Except for those who are in the habit of exercising those loopholes.)
  29. X    - Chris' map is enclosed.
  30. X    - The "charac" file is not compatible with older versions of Phantasia
  31. X      (3.3.1 and 3.3.1+).  A 'convert' program is provided to convert your
  32. X      old file to the new format.  See Makefile for details.
  33. X    - Movements can be made with HJKL for WSNE, respectively.
  34. X    - Players may examine others while playing ('x') option.
  35. X    - Monsters are now stored in a binary data base, to speed calling
  36. X      monsters, and to ease formatting of monster listings.
  37. X    - Taxes are collected on all gold and gems.
  38. X    - Dead players can be resurrected by the 'wizard'.
  39. X    - 'setup' is smarter, although not as smart as it should be.
  40. X    - Players can change their names and passwords
  41. X
  42. XPORTABILTY:
  43. X
  44. X    I have tried to make this as non-machine/system specific as possible.
  45. X
  46. X    All identifiers are unique to 7 characters or less, dual case.
  47. X
  48. X    The code WILL NOT fit on a 16-bit machine without separate I/D.
  49. X
  50. X    Stdio MUST support fopen() with mode "r+".  I think this is true
  51. X    for all Version 7 and later.
  52. X
  53. X    'curses' library functions are required.
  54. X
  55. X    All problems/solutions with portability should be reported to me,
  56. X    and fixes will be included in subsequent versions of this software.
  57. X
  58. X
  59. XPlease send me any bugs, (of which I am sure there are many), you may find,
  60. Xbut PLEASE be specific.  I cannot correct a bug which is described as:
  61. X
  62. X    "When I choose a character type, it blows up."
  63. X
  64. X    (What blows up?  What exactly was printed at the terminal?
  65. X    Which character type was chosen?  Etc. . . ?)
  66. X
  67. XAlso, please tell me which version of UN*X you are running, and upon
  68. Xwhich type of hardware.
  69. X
  70. XI will also do my best to help anyone with problems just trying to
  71. Xget the game running.  Again, I need to know which version of UN*X
  72. Xand what type of CPU.  Also, a copy of the output from 'make'
  73. Xwould be extremely useful.
  74. X
  75. XAny and all ideas/suggestions/additions are more than welcome.  If
  76. Xyou feel strongly enough about it, write the change and send it to me,
  77. Xand I will do my best to incorporate it in the next version of Phantasia.
  78. XOtherwise, I will give serious thought to adding it myself.
  79. X
  80. XFollow the directions in the Makefile CAREFULLY to set up the game.
  81. XRead the comments at the beginning of 'main.c', if you haven't already.
  82. X
  83. XEnjoy.
  84. X
  85. XTed Estes
  86. XAT&T Information Systems
  87. XSkokie, IL  60077
  88. X
  89. X...!ihnp4!ttrdc!ttrda!estes
  90. !EOR!
  91. echo x - Makefile
  92. sed 's/^X//' > Makefile << '!EOR!'
  93. X# Makefile for Phantasia 3.3.2
  94. X#
  95. X# To create game:
  96. X#
  97. X# 1)  Set up a directory where the game and its support files will live.
  98. X#        (It is suggested that the source be kept somewhere else.)
  99. X#
  100. X# 2)  Set up the variables in Makefile CAREFULLY to reflect your
  101. X#        particular situation.
  102. X#
  103. X# 3)  Check out ok_to_play() at the end of main.c if you want to include
  104. X#        code to restrict access at certain times.
  105. X#
  106. X# 4)  'make install' and sit back and watch.
  107. X#
  108. X# NOTE:  'setup' MUST be executed before trying to run 'phantasia'.
  109. X#     The install procedure does this for you.
  110. X#
  111. X#
  112. X# To convert from 3.3.1 or 3.3.1+ to 3.3.2:
  113. X#
  114. X# 1)    'make convert'  (3.3.1+: 'make PLUS=-DPHANTPLUS convert')
  115. X#
  116. X# 2)    Move 'newcharacs' to 'characs'.
  117. X#
  118. X
  119. XRM =        -rm
  120. XSHAR =        /d2/estes/bin/shar
  121. X# Tell 'make' to use /bin/sh for all commands.
  122. XSHELL =        /bin/sh
  123. X
  124. X# PLOTDEVICE is used for plotting the map.
  125. X# Change as appropriate.
  126. XPLOTDEVICE =    > /dev/tty
  127. X
  128. X# Add '-ljobs' to LDFLAGS if 4.1bsd; add -ltermlib if not SVR2.
  129. X# Need separate i/d space on small machines.
  130. X# May need '-f' on machines without floating point hardware.
  131. XLDFLAGS =    -lm -lcurses
  132. X
  133. X# DEST is where the program and its support files reside
  134. XDEST =        /a2/estes/phant
  135. X
  136. X# The following are program constants which are implementation dependent.
  137. X#
  138. X# DEST is passed on.  Note that there is no closing quote here.
  139. X# WIZARD is the login of the one who will clean up things.
  140. X# UID is the uid of game wizard.
  141. X# define OK_TO_PLAY to restrict playing access at certain times.
  142. X#    Also see function ok_to_play() in main.c, and tailor to your own needs.
  143. X# define ENEMY to include code for checking of a 'hit list' of resricted 
  144. X#    accounts.  The list of logins goes in the file 'enemy'.
  145. X# SHELL is the default shell for shell escapes.  If SHELL is not defined,
  146. X#    shell escapes are not enabled.
  147. X# define BSD41 for 4.1bsd
  148. X# define BSD42 for 4.2bsd
  149. X# define SYS3 for System III, or similar (like Version 7)
  150. X# define SYS5 for System V
  151. X# If you don't have 'strchr()', put '-Dstrchr=index' below.
  152. X# May need '-I/usr/include/sys' for 4.2bsd.
  153. XCFLAGS =     -O \
  154. X        -DDEST=\"${DEST} \
  155. X        -DWIZARD=\"estes\" \
  156. X        -DUID=419 \
  157. X        -DOK_TO_PLAY \
  158. X        -DENEMY \
  159. X        -DSHELL=\"/bin/sh\" \
  160. X        -DSYS5
  161. X
  162. XCFILES =    main.c fight.c io.c interplayer.c gamesupport.c misc.c phantglobs.c
  163. XOFILES =    main.o fight.o io.o interplayer.o gamesupport.o misc.o phantglobs.o
  164. XHFILES =    phantdefs.h phantstruct.h macros.h include.h
  165. X
  166. Xall:        phantasia setup phant.help
  167. X
  168. X# Make the game.
  169. Xphantasia:    ${OFILES}
  170. X        ${CC} ${OFILES} ${LDFLAGS} -o phantasia
  171. X
  172. X${OFILES}:    ${HFILES}
  173. X
  174. X# Make the initialization program.
  175. Xsetup:        phantglobs.o setup.o monsters.asc
  176. X        ${CC} phantglobs.o setup.o ${LDFLAGS} -o setup
  177. X
  178. Xsetup.o:    ${HFILES}
  179. X
  180. X# Make documentation.
  181. X# The flags below on tbl and nroff are to make a line printable version.
  182. Xphant.help:    phant.nr
  183. X        tbl -TX phant.nr | nroff -Ttn300 -man > phant.help
  184. X
  185. X# Install game and documentation.  Initialize.
  186. Xinstall:    all
  187. X        cp phantasia phant.help ${DEST}
  188. X        chmod 755 ${DEST}
  189. X        chmod 4711 ${DEST}/phantasia
  190. X        chmod 644 ${DEST}/phant.help
  191. X        setup
  192. X
  193. X# Make Phantasia map.
  194. X# Change the map commands reflect your installation.
  195. X# Pre-System III installations may use 'plot' instead of 'tplot'.
  196. Xmap:        map.c
  197. X        cc -O map.c -lplot -o map
  198. X        map | tplot -t4014 ${PLOTDEVICE}
  199. X
  200. X# Convert old character file to new format.
  201. X# 'convert' is meant to be run only once.
  202. X# PLUS = PHANTPLUS for conversion from 3.3.1+.
  203. Xconvert:    convert.c oldplayer.h phantstruct.h
  204. X        ${CC} ${CFLAGS} ${PLUS} convert.c ${LDFLAGS} -o convert
  205. X        convert
  206. X        @echo "New data is in newcharacs."
  207. X
  208. X# Clean up directory after installation.
  209. Xclean:
  210. X        ${RM} -f *.o phantasia phant.help phant.pt?
  211. X
  212. X# Make 'shell archives'.
  213. X# All source files barely fit into 5 archives, and must be
  214. X# carefully grouped to do so.
  215. Xshar:        ${CFILES} ${HFILES} phant.nr Makefile map.c convert.c oldplayer.h
  216. X        ${SHAR} README Makefile main.c include.h phantstruct.h \
  217. X            map.c monsters.asc > phant.pt1
  218. X        ${SHAR} phantglobs.h phantglobs.c fight.c \
  219. X            convert.c > phant.pt2
  220. X        ${SHAR} interplayer.c gamesupport.c io.c > phant.pt3
  221. X        ${SHAR} macros.h phantdefs.h setup.c misc.c \
  222. X            oldplayer.h > phant.pt4
  223. X        ${SHAR} phant.nr interplayer.c > phant.pt5
  224. X
  225. !EOR!
  226. echo x - main.c
  227. sed 's/^X//' > main.c << '!EOR!'
  228. X/*
  229. X * Phantasia 3.3.2 -- Interterminal fantasy game
  230. X *
  231. X * Edward A. Estes
  232. X * AT&T, March 12, 1986
  233. X */
  234. X
  235. X/* DISCLAIMER:
  236. X *
  237. X * This game is distributed for free as is.  It is not guaranteed to work
  238. X * in every conceivable environment.  It is not even guaranteed to work
  239. X * in ANY environment.
  240. X *
  241. X * This game is distributed without notice of copyright, therefore it
  242. X * may be used in any manner the recipient sees fit.  However, the
  243. X * author assumes no responsibility for maintaining or revising this
  244. X * game, in its original form, or any derivitives thereof.
  245. X *
  246. X * The author shall not be responsible for any loss, cost, or damage,
  247. X * including consequential damage, caused by reliance on this material.
  248. X *
  249. X * The author makes no warranties, express or implied, including warranties
  250. X * of merchantability or fitness for a particular purpose or use.
  251. X *
  252. X * AT&T is in no way connected with this game.
  253. X */
  254. X
  255. X/*
  256. X * The program allocates as much file space as it needs to store characters,
  257. X * so the possibility exists for the character file to grow without bound.
  258. X * The file is purged upon normal entry to try to avoid that problem.
  259. X * A similar problem exists for energy voids.  To alleviate the problem here,
  260. X * the void file is cleared with every new king, and a limit is placed
  261. X * on the size of the energy void file.
  262. X */
  263. X
  264. X/*
  265. X * Put one line of text into the file 'motd' for announcements, etc.
  266. X */
  267. X
  268. X/*
  269. X * If ENEMY is #defined, a list of restricted login names is checked
  270. X * in the file 'enemy'.  These names are listed, one per line, with
  271. X * no trailing blanks.
  272. X */
  273. X
  274. X/*
  275. X * The scoreboard file is updated when someone dies, and keeps track
  276. X * of the highest character to date for that login.
  277. X * Being purged from the character file does not cause the scoreboard
  278. X * to be updated.
  279. X */
  280. X
  281. X/*
  282. X * All source files are set up for 'vi' with shiftwidth=4, tabstop=8. 
  283. X */
  284. X
  285. X/* */
  286. X
  287. X/*
  288. X * main.c    Main routines for Phantasia
  289. X */
  290. X
  291. X#include "include.h"
  292. X
  293. X/***************************************************************************
  294. X/ FUNCTION NAME: main()
  295. X/
  296. X/ FUNCTION: initialize state, and call main process
  297. X/
  298. X/ AUTHOR: E. A. Estes, 12/4/85
  299. X/
  300. X/ ARGUMENTS:
  301. X/    int    argc - argument count
  302. X/    char    **argv - argument vector
  303. X/
  304. X/ RETURN VALUE: none
  305. X/
  306. X/ MODULES CALLED: monstlist(), checkenemy(), ok_to_play(), activelist(), 
  307. X/    throneroom(), checkbattle(), readmessage(), changestats(), writerecord(), 
  308. X/    tradingpost(), adjuststats(), recallplayer(), displaystats(), checktampered(), 
  309. X/    fabs(), rollnewplayer(), time(), exit(), sqrt(), floor(), wmove(), 
  310. X/    signal(), strcat(), purgeoldplayers(), getuid(), isatty(), wclear(), 
  311. X/    strcpy(), system(), altercoordinates(), cleanup(), waddstr(), procmain(), 
  312. X/    playinit(), leavegame(), localtime(), getanswer(), neatstuff(), initstate(), 
  313. X/    scorelist(), titlelist()
  314. X/
  315. X/ GLOBAL INPUTS: *Login, Throne, Wizard, Player, *stdscr, Changed, Databuf[], 
  316. X/    Fileloc, Helpfile[], Stattable[]
  317. X/
  318. X/ GLOBAL OUTPUTS: Wizard, Player, Changed, Fileloc, Timeout, *Statptr
  319. X/
  320. X/ DESCRIPTION:
  321. X/    Process arguments, initialize program, and loop forever processing
  322. X/    player input.
  323. X/
  324. X/***************************************************************************/
  325. X
  326. Xmain(argc, argv)
  327. Xint    argc;
  328. Xchar    **argv;
  329. X{
  330. Xbool    noheader = FALSE;    /* set if don't want header */
  331. Xbool    headeronly = FALSE;    /* set if only want header */
  332. Xbool    examine = FALSE;    /* set if examine a character */
  333. Xlong    seconds;        /* for time of day */
  334. Xdouble    dtemp;            /* for temporary calculations */
  335. X
  336. X    initstate();        /* init globals */
  337. X
  338. X#ifdef ENEMY
  339. X    checkenemy();        /* check if denied access */
  340. X#endif
  341. X
  342. X    /* process arguments */
  343. X    while (--argc && (*++argv)[0] == '-')
  344. X    switch ((*argv)[1])
  345. X        {
  346. X        case 's':    /* short */
  347. X        noheader = TRUE;
  348. X        break;
  349. X
  350. X        case 'H':    /* Header */
  351. X        headeronly = TRUE;
  352. X        break;
  353. X
  354. X        case 'a':    /* all users */
  355. X        activelist();
  356. X        cleanup(TRUE);
  357. X        /*NOTREACHED*/
  358. X
  359. X        case 'p':    /* purge old players */
  360. X        purgeoldplayers();
  361. X        cleanup(TRUE);
  362. X        /*NOTREACHED*/
  363. X
  364. X        case 'S':    /* set 'Wizard' */
  365. X        Wizard = (getuid() == UID);
  366. X        break;
  367. X
  368. X        case 'x':    /* examine */
  369. X        examine = TRUE;
  370. X        break;
  371. X
  372. X        case 'm':    /* monsters */
  373. X        monstlist();
  374. X        cleanup(TRUE);
  375. X        /*NOTREACHED*/
  376. X
  377. X        case 'b':    /* scoreboard */
  378. X        scorelist();
  379. X        cleanup(TRUE);
  380. X        /*NOTREACHED*/
  381. X
  382. X        case 'h':    /* help */
  383. X        cleanup(FALSE);
  384. X        strcpy(Databuf, "cat ");
  385. X        system(strcat(Databuf, Helpfile));
  386. X        exit(0);
  387. X        /*NOTREACHED*/
  388. X        }
  389. X
  390. X    if (!isatty(0))        /* don't let non-tty's play */
  391. X    cleanup(TRUE);
  392. X    /*NOTREACHED*/
  393. X
  394. X    playinit();            /* set up to catch signals, init curses */
  395. X
  396. X    if (examine)
  397. X    {
  398. X    changestats(FALSE);
  399. X    cleanup(TRUE);
  400. X    /*NOTREACHED*/
  401. X    }
  402. X
  403. X    if (!noheader)
  404. X    {
  405. X    titlelist();
  406. X    purgeoldplayers();    /* clean up old characters */
  407. X    }
  408. X
  409. X    if (headeronly)
  410. X    cleanup(TRUE);
  411. X    /*NOTREACHED*/
  412. X
  413. X#ifdef OK_TO_PLAY
  414. X    if (!ok_to_play())
  415. X    {
  416. X    mvaddstr(23, 27, "Sorry, you can't play now.\n");
  417. X    cleanup(TRUE);
  418. X    /*NOTREACHED*/
  419. X    }
  420. X#endif
  421. X
  422. X    do
  423. X    /* get the player structure filled */
  424. X    {
  425. X    Fileloc = -1L;
  426. X
  427. X    mvaddstr(22, 17, "Do you have a character to run [Q = Quit] ? ");
  428. X
  429. X    switch (getanswer("NYQ", FALSE))
  430. X        {
  431. X        case 'Y':
  432. X        Fileloc = recallplayer();
  433. X        break;
  434. X
  435. X        case 'Q':
  436. X        cleanup(TRUE);
  437. X        /*NOTREACHED*/
  438. X
  439. X        default:
  440. X        Fileloc = rollnewplayer();
  441. X        break;
  442. X        }
  443. X    clear();
  444. X    }
  445. X    while (Fileloc < 0L);
  446. X
  447. X    if (Player.p_level > 5.0)
  448. X    /* low level players have long timeout */
  449. X    Timeout = TRUE;
  450. X
  451. X    /* update some important player statistics */
  452. X    strcpy(Player.p_login, Login);
  453. X    time(&seconds);
  454. X    Player.p_lastused = localtime(&seconds)->tm_yday;
  455. X    Player.p_status = S_PLAYING;
  456. X    writerecord(&Player, Fileloc);
  457. X
  458. X    Statptr = &Stattable[Player.p_type];    /* initialize pointer */
  459. X
  460. X    /* catch interrupts */
  461. X#ifdef    BSD41
  462. X    sigset(SIGINT, interrupt);
  463. X#endif
  464. X#ifdef    BSD42
  465. X    signal(SIGINT, interrupt);
  466. X#endif
  467. X#ifdef    SYS3
  468. X    signal(SIGINT, interrupt);
  469. X#endif
  470. X#ifdef    SYS5
  471. X    signal(SIGINT, interrupt);
  472. X#endif
  473. X
  474. X    altercoordinates(Player.p_x, Player.p_y, A_FORCED);    /* set some flags */
  475. X
  476. X    clear();
  477. X
  478. X    for (;;)
  479. X    /* loop forever, processing input */
  480. X    {
  481. X#ifdef OK_TO_PLAY
  482. X    if (!ok_to_play())
  483. X        {
  484. X        mvaddstr(6, 0, "Whoops!  Can't play now.\n");
  485. X        leavegame();
  486. X        /*NOTREACHED*/
  487. X        }
  488. X#endif
  489. X
  490. X    adjuststats();        /* cleanup stats */
  491. X
  492. X    if (Throne && Player.p_crowns == 0 && Player.p_specialtype != SC_KING)
  493. X        /* not allowed on throne -- move */
  494. X        {
  495. X        mvaddstr(5,0,"You're not allowed in the Lord's Chamber without a crown.\n");
  496. X        altercoordinates(0.0, 0.0, A_NEAR);
  497. X        }
  498. X
  499. X    if (Player.p_status != S_CLOAKED
  500. X        /* not cloaked */
  501. X        && (dtemp = fabs(Player.p_x)) == fabs(Player.p_y)
  502. X        /* |x| = |y| */
  503. X        && !Throne)
  504. X        /* not on throne */
  505. X        {
  506. X        dtemp = sqrt(dtemp / 100.0);
  507. X        if (floor(dtemp) == dtemp)
  508. X        /* |x| / 100 == n*n; at a trading post */
  509. X        {
  510. X        tradingpost();
  511. X        clear();
  512. X        }
  513. X        }
  514. X
  515. X    checktampered();    /* check for energy voids, etc. */
  516. X    checkbattle();        /* check for player to player battle */
  517. X    neatstuff();        /* gurus, medics, etc. */
  518. X
  519. X    if (Player.p_status == S_CLOAKED)
  520. X        /* costs 3 mana per turn to be cloaked */
  521. X        if (Player.p_mana > 3.0)
  522. X        Player.p_mana -= 3.0;
  523. X        else
  524. X        /* ran out of mana, uncloak */
  525. X        {
  526. X        Player.p_status = S_PLAYING;
  527. X        Changed = TRUE;
  528. X        }
  529. X
  530. X    if (Player.p_status != S_PLAYING && Player.p_status != S_CLOAKED)
  531. X        /* change status back to S_PLAYING */
  532. X        {
  533. X        Player.p_status = S_PLAYING;
  534. X        Changed = TRUE;
  535. X        }
  536. X
  537. X    if (Changed)
  538. X        /* update file only if important stuff has changed */
  539. X        {
  540. X        writerecord(&Player, Fileloc);
  541. X        Changed = FALSE;
  542. X        continue;
  543. X        }
  544. X
  545. X    readmessage();            /* read message, if any */
  546. X
  547. X    displaystats();            /* print statistics */
  548. X
  549. X    move(6, 0);
  550. X
  551. X    if (Throne)
  552. X        /* maybe make king, print prompt, etc. */
  553. X        throneroom();
  554. X
  555. X    /* print status line */
  556. X    addstr("1:Move  2:Players  3:Talk  4:Stats  5:Quit  ");
  557. X    if (Player.p_level >= MEL_CLOAK && Player.p_magiclvl >= ML_CLOAK)
  558. X        addstr("6:Cloak  ");
  559. X    if (Player.p_level >= MEL_TELEPORT && Player.p_magiclvl >= ML_TELEPORT)
  560. X        addstr("7:Teleport  ");
  561. X    if (Player.p_specialtype >= SC_COUNCIL || Wizard)
  562. X        addstr("8:Intervene  ");
  563. X
  564. X    procmain();            /* process input */
  565. X    }
  566. X}
  567. X/* */
  568. X/************************************************************************
  569. X/
  570. X/ FUNCTION NAME: initstate()
  571. X/
  572. X/ FUNCTION: initialize some important global variable
  573. X/
  574. X/ AUTHOR: E. A. Estes, 12/4/85
  575. X/
  576. X/ ARGUMENTS: none
  577. X/
  578. X/ RETURN VALUE: none
  579. X/
  580. X/ MODULES CALLED: time(), fopen(), srand(), error(), getuid(), getlogin(), 
  581. X/    getpwuid()
  582. X/
  583. X/ GLOBAL INPUTS: Peoplefile[], Voidfile[], Messfile[], Monstfile[]
  584. X/
  585. X/ GLOBAL OUTPUTS: *Energyvoidfp, Echo, Marsh, *Login, Users, Beyond, 
  586. X/    Throne, Wizard, Changed, Okcount, Timeout, Windows, *Monstfp, *Messagefp, 
  587. X/    *Playersfp
  588. X/
  589. X/ DESCRIPTION:
  590. X/    Set global flags, and open files which remain open.
  591. X/
  592. X/************************************************************************/
  593. X
  594. Xinitstate()
  595. X{
  596. X    Beyond = FALSE;
  597. X    Marsh = FALSE;
  598. X    Throne = FALSE;
  599. X    Changed = FALSE;
  600. X    Wizard = FALSE;
  601. X    Timeout = FALSE;
  602. X    Users = 0;
  603. X    Windows = FALSE;
  604. X    Echo = TRUE;
  605. X#ifdef OK_TO_PLAY
  606. X    Okcount = 0;
  607. X#endif
  608. X
  609. X    /* setup login name */
  610. X    if ((Login = getlogin()) == NULL)
  611. X    Login = getpwuid(getuid())->pw_name;
  612. X    
  613. X    /* open some files */
  614. X    if ((Playersfp = fopen(Peoplefile, "r+")) == NULL)
  615. X    error(Peoplefile);
  616. X    /*NOTREACHED*/
  617. X
  618. X    if ((Monstfp = fopen(Monstfile, "r+")) == NULL)
  619. X    error(Monstfile);
  620. X    /*NOTREACHED*/
  621. X
  622. X    if ((Messagefp = fopen(Messfile, "r")) == NULL)
  623. X    error(Messfile);
  624. X    /*NOTREACHED*/
  625. X
  626. X    if ((Energyvoidfp = fopen(Voidfile, "r")) == NULL)
  627. X    error(Voidfile);
  628. X    /*NOTREACHED*/
  629. X
  630. X    srand((unsigned) time((long *) NULL));    /* prime random numbers */
  631. X}
  632. X/* */
  633. X/************************************************************************
  634. X/
  635. X/ FUNCTION NAME: rollnewplayer()
  636. X/
  637. X/ FUNCTION: roll up a new character
  638. X/
  639. X/ AUTHOR: E. A. Estes, 12/4/85
  640. X/
  641. X/ ARGUMENTS: none
  642. X/
  643. X/ RETURN VALUE: none
  644. X/
  645. X/ MODULES CALLED: initplayer(), allocrecord(), truncstring(), fabs(), wmove(), 
  646. X/    wclear(), sscanf(), strcmp(), genchar(), waddstr(), findname(), mvprintw(), 
  647. X/    getanswer(), getstring()
  648. X/
  649. X/ GLOBAL INPUTS: Other, Wizard, Player, *stdscr, Databuf[]
  650. X/
  651. X/ GLOBAL OUTPUTS: Echo
  652. X/
  653. X/ DESCRIPTION:
  654. X/    Prompt player, and roll up new character.
  655. X/
  656. X/************************************************************************/
  657. X
  658. Xlong
  659. Xrollnewplayer()
  660. X{
  661. Xint    chartype;    /* character type */
  662. Xint    ch;        /* input */
  663. X
  664. X    initplayer(&Player);        /* initialize player structure */
  665. X
  666. X    clear();
  667. X    mvaddstr(4, 21, "Which type of character do you want:");
  668. X    mvaddstr(8, 4, "1:Magic User  2:Fighter  3:Elf  4:Dwarf  5:Halfling  6:Experimento  ");
  669. X    if (Wizard)
  670. X    addstr("7:Super  ? ");
  671. X    else
  672. X    addstr("?  ");
  673. X
  674. X    chartype = getanswer("2134567", FALSE);
  675. X
  676. X    do
  677. X    {
  678. X    genchar(chartype);        /* roll up a character */
  679. X
  680. X    /* print out results */
  681. X    mvprintw(12, 14,
  682. X        "Strength    :  %2.0f  Quickness:  %2.0f  Mana       :  %2.0f\n",
  683. X        Player.p_strength, Player.p_quickness, Player.p_mana);
  684. X    mvprintw(13, 14,
  685. X        "Energy Level:  %2.0f  Brains   :  %2.0f  Magic Level:  %2.0f\n",
  686. X        Player.p_energy, Player.p_brains, Player.p_magiclvl);
  687. X
  688. X    if (Player.p_type == C_EXPER || Player.p_type == C_SUPER)
  689. X        break;
  690. X
  691. X    mvaddstr(14, 14, "Type '1' to keep >");
  692. X    ch = getanswer(" ", TRUE);
  693. X    }
  694. X    while (ch != '1');
  695. X
  696. X    if (Player.p_type == C_EXPER || Player.p_type == C_SUPER)
  697. X    /* get coordinates for experimento */
  698. X    for (;;)
  699. X        {
  700. X        mvaddstr(16, 0, "Enter the X Y coordinates of your experimento ? ");
  701. X        getstring(Databuf, SZ_DATABUF);
  702. X        sscanf(Databuf, "%F %F", &Player.p_x, &Player.p_y);
  703. X
  704. X        if (fabs(Player.p_x) > D_EXPER || fabs(Player.p_y) > D_EXPER)
  705. X        mvaddstr(17, 0, "Invalid coordinates.  Try again.\n");
  706. X        else
  707. X        break;
  708. X        }
  709. X
  710. X    for (;;)
  711. X    /* name the new character */
  712. X    {
  713. X    mvprintw(18, 0,
  714. X        "Give your character a name [up to %d characters] ?  ", SZ_NAME - 1);
  715. X    getstring(Player.p_name, SZ_NAME);
  716. X    truncstring(Player.p_name);        /* remove trailing blanks */
  717. X
  718. X    if (Player.p_name[0] == '\0')
  719. X        /* no null names */
  720. X        mvaddstr(19, 0, "Invalid name.");
  721. X    else if (findname(Player.p_name, &Other) >= 0L)
  722. X        /* cannot have duplicate names */
  723. X        mvaddstr(19, 0, "Name already in use.");
  724. X    else
  725. X        /* name is acceptable */
  726. X        break;
  727. X
  728. X    addstr("  Pick another.\n");
  729. X    }
  730. X
  731. X    /* get a password for character */
  732. X    Echo = FALSE;
  733. X
  734. X    do
  735. X    {
  736. X    mvaddstr(20, 0, "Give your character a password [up to 8 characters] ? ");
  737. X    getstring(Player.p_password, SZ_PASSWORD);
  738. X    mvaddstr(21, 0, "One more time to verify ? ");
  739. X    getstring(Databuf, SZ_PASSWORD);
  740. X    }
  741. X    while (strcmp(Player.p_password, Databuf) != 0);
  742. X
  743. X    Echo = TRUE;
  744. X
  745. X    return(allocrecord());
  746. X}
  747. X/* */
  748. X/************************************************************************
  749. X/
  750. X/ FUNCTION NAME: procmain()
  751. X/
  752. X/ FUNCTION: process input from player
  753. X/
  754. X/ AUTHOR: E. A. Estes, 12/4/85
  755. X/
  756. X/ ARGUMENTS: none
  757. X/
  758. X/ RETURN VALUE: none
  759. X/
  760. X/ MODULES CALLED: dotampered(), changestats(), inputoption(), allstatslist(), 
  761. X/    fopen(), wmove(), random(), sscanf(), fclose(), altercoordinates(), 
  762. X/    waddstr(), fprintf(), distance(), userlist(), leavegame(), encounter(), 
  763. X/    getstring(), wclrtobot()
  764. X/
  765. X/ GLOBAL INPUTS: Circle, Illcmd[], Throne, Wizard, Player, *stdscr, 
  766. X/    Databuf[], Illmove[], Messfile[]
  767. X/
  768. X/ GLOBAL OUTPUTS: Player, Changed
  769. X/
  770. X/ DESCRIPTION:
  771. X/    Process main menu options.
  772. X/
  773. X/************************************************************************/
  774. X
  775. Xprocmain()
  776. X{
  777. Xint    ch;            /* input */
  778. Xdouble    x;            /* desired new x coordinate */
  779. Xdouble    y;            /* desired new y coordinate */
  780. Xdouble    temp;            /* for temporary calculations */
  781. XFILE    *fp;            /* for opening files */
  782. Xregister int    loop;        /* a loop counter */
  783. Xbool    hasmoved = FALSE;    /* set if player has moved */
  784. X
  785. X    ch = inputoption();
  786. X    mvaddstr(4, 0, "\n\n");        /* clear status area */
  787. X
  788. X    move(7, 0);
  789. X    clrtobot();            /* clear data on bottom area of screen */
  790. X
  791. X    if (Player.p_specialtype == SC_VALAR && (ch == '1' || ch == '7'))
  792. X    /* valar cannot move */
  793. X    ch = ' ';
  794. X
  795. X    switch (ch)
  796. X    {
  797. X    case 'K':        /* move up/north */
  798. X    case 'N':
  799. X        x = Player.p_x;
  800. X        y = Player.p_y + MAXMOVE();
  801. X        hasmoved = TRUE;
  802. X        break;
  803. X
  804. X    case 'J':        /* move down/south */
  805. X    case 'S':
  806. X        x = Player.p_x;
  807. X        y = Player.p_y - MAXMOVE();
  808. X        hasmoved = TRUE;
  809. X        break;
  810. X
  811. X    case 'L':        /* move right/east */
  812. X    case 'E':
  813. X        x = Player.p_x + MAXMOVE();
  814. X        y = Player.p_y;
  815. X        hasmoved = TRUE;
  816. X        break;
  817. X
  818. X    case 'H':        /* move left/west */
  819. X    case 'W':
  820. X        x = Player.p_x - MAXMOVE();
  821. X        y = Player.p_y;
  822. X        hasmoved = TRUE;
  823. X        break;
  824. X
  825. X    default:    /* rest */
  826. X        Player.p_energy += (Player.p_maxenergy + Player.p_shield) / 15.0
  827. X        + Player.p_level / 3.0 + 2.0;
  828. X        Player.p_energy =
  829. X        MIN(Player.p_energy, Player.p_maxenergy + Player.p_shield);
  830. X
  831. X        if (Player.p_status != S_CLOAKED)
  832. X        /* cannot find mana if cloaked */
  833. X        {
  834. X        Player.p_mana += (Circle + Player.p_level) / 4.0;
  835. X
  836. X        if (random() < 0.2 && Player.p_status == S_PLAYING && !Throne)
  837. X            /* wandering monster */
  838. X            encounter(-1);
  839. X        }
  840. X        break;
  841. X
  842. X    case 'X':        /* change/examine a character */
  843. X        changestats(TRUE);
  844. X        break;
  845. X
  846. X    case '1':        /* move */
  847. X        for (loop = 3; loop; --loop)
  848. X        {
  849. X        mvaddstr(4, 0, "X Y Coordinates ? ");
  850. X        getstring(Databuf, SZ_DATABUF);
  851. X
  852. X        if (sscanf(Databuf, "%F %F", &x, &y) != 2)
  853. X            mvaddstr(5, 0, "Try again\n");
  854. X        else if (distance(Player.p_x, x, Player.p_y, y) > MAXMOVE())
  855. X            ILLMOVE();
  856. X        else
  857. X            {
  858. X            hasmoved = TRUE;
  859. X            break;
  860. X            }
  861. X        }
  862. X        break;
  863. X
  864. X    case '2':        /* players */
  865. X        userlist(TRUE);
  866. X        break;
  867. X
  868. X    case '3':        /* message */
  869. X        mvaddstr(4, 0, "Message ? ");
  870. X        getstring(Databuf, SZ_DATABUF);
  871. X        /* we open the file for writing to erase any data which is already there */
  872. X        fp = fopen(Messfile, "w");
  873. X        if (Databuf[0] != '\0')
  874. X        fprintf(fp, "%s: %s", Player.p_name, Databuf);
  875. X        fclose(fp);
  876. X        break;
  877. X
  878. X    case '4':        /* stats */
  879. X        allstatslist();
  880. X        break;
  881. X
  882. X    case '5':        /* good-bye */
  883. X        leavegame();
  884. X        /*NOTREACHED*/
  885. X
  886. X    case '6':        /* cloak */
  887. X        if (Player.p_level < MEL_CLOAK || Player.p_magiclvl < ML_CLOAK)
  888. X        ILLCMD();
  889. X        else if (Player.p_status == S_CLOAKED)
  890. X        Player.p_status = S_PLAYING;
  891. X        else if (Player.p_mana < MM_CLOAK)
  892. X        mvaddstr(5, 0, "No mana left.\n");
  893. X        else
  894. X        {
  895. X        Changed = TRUE;
  896. X        Player.p_mana -= MM_CLOAK;
  897. X        Player.p_status = S_CLOAKED;
  898. X        }
  899. X        break;
  900. X
  901. X    case '7':    /* teleport */
  902. X        /*
  903. X         * conditions for teleport
  904. X         *    - 20 per (level plus magic level)
  905. X         *    - OR council of the wise or valar or ex-valar
  906. X         *    - OR transport from throne
  907. X         * transports from throne cost no mana
  908. X         */
  909. X        if (Player.p_level < MEL_TELEPORT || Player.p_magiclvl < ML_TELEPORT)
  910. X        ILLCMD();
  911. X        else 
  912. X        for (loop = 3; loop; --loop)
  913. X            {
  914. X            mvaddstr(4, 0, "X Y Coordinates ? ");
  915. X            getstring(Databuf, SZ_DATABUF);
  916. X
  917. X            if (sscanf(Databuf, "%F %F", &x, &y) == 2)
  918. X            {
  919. X            temp = distance(Player.p_x, x, Player.p_y, y);
  920. X            if (!Throne
  921. X                /* can transport anywhere from throne */
  922. X                && Player.p_specialtype <= SC_COUNCIL
  923. X                /* council, valar can transport anywhere */
  924. X                && temp > (Player.p_level + Player.p_magiclvl) * 20.0)
  925. X                /* can only move 20 per exp. level + mag. level */
  926. X                ILLMOVE();
  927. X            else
  928. X                {
  929. X                temp = (temp / 75.0 + 1.0) * 20.0;    /* mana used */
  930. X
  931. X                if (!Throne && temp > Player.p_mana)
  932. X                mvaddstr(5, 0, "Not enough power for that distance.\n");
  933. X                else
  934. X                {
  935. X                if (!Throne)
  936. X                    Player.p_mana -= temp;
  937. X                hasmoved = TRUE;
  938. X                break;
  939. X                }
  940. X                }
  941. X            }
  942. X            }
  943. X        break;
  944. X
  945. X    case 'C':
  946. X    case '9':        /* monster */
  947. X        if (Throne)
  948. X        /* no monsters while on throne */
  949. X        mvaddstr(5, 0, "No monsters in the chamber!\n");
  950. X        else if (Player.p_specialtype != SC_VALAR)
  951. X        /* the valar cannot call monsters */
  952. X        {
  953. X        Player.p_sin += 1e-6;
  954. X        encounter(-1);
  955. X        }
  956. X        break;
  957. X
  958. X    case '0':        /* decree */
  959. X        if (Wizard || Player.p_specialtype == SC_KING && Throne)
  960. X        /* kings must be on throne to decree */
  961. X        dotampered();
  962. X        else
  963. X        ILLCMD();
  964. X        break;
  965. X
  966. X    case '8':        /* intervention */
  967. X        if (Wizard || Player.p_specialtype >= SC_COUNCIL)
  968. X        dotampered();
  969. X        else
  970. X        ILLCMD();
  971. X        break;
  972. X    }
  973. X
  974. X    if (hasmoved)
  975. X    /* player has moved -- alter coordinates, and do random monster */
  976. X    {
  977. X    altercoordinates(x, y, A_SPECIFIC);
  978. X
  979. X    if (random() < 0.2 && Player.p_status == S_PLAYING && !Throne)
  980. X        encounter(-1);
  981. X    }
  982. X}
  983. X/* */
  984. X#ifdef    ENEMY
  985. X/************************************************************************
  986. X/
  987. X/ FUNCTION NAME: checkenemy()
  988. X/
  989. X/ FUNCTION: check login name against enemy list
  990. X/
  991. X/ AUTHOR: E. A. Estes, 12/4/85
  992. X/
  993. X/ ARGUMENTS: none
  994. X/
  995. X/ RETURN VALUE: none
  996. X/
  997. X/ MODULES CALLED: fopen(), fgets(), strcmp(), fclose(), printf(), cleanup()
  998. X/
  999. X/ GLOBAL INPUTS: *Login, Databuf[], Enemyfile[]
  1000. X/
  1001. X/ GLOBAL OUTPUTS: none
  1002. X/
  1003. X/ DESCRIPTION:
  1004. X/    The enemy file has a list of login names which are denied
  1005. X/    access to Phantasia.
  1006. X/    We scan this list and exit if the current login name is
  1007. X/    found in the list.
  1008. X/
  1009. X/************************************************************************/
  1010. X
  1011. Xcheckenemy()
  1012. X{
  1013. XFILE    *fp;        /* to open enemy file */
  1014. X
  1015. X    /* check hit list of restricted accounts */
  1016. X    if ((fp = fopen(Enemyfile, "r")) != NULL)
  1017. X    {
  1018. X    while (fgets(Databuf, SZ_DATABUF, fp) != NULL)
  1019. X        if (strcmp(Login, Databuf) == 0)
  1020. X        {
  1021. X        printf ("The Phantasia privileges for the account \"%s\" have been revoked.\n", Login);
  1022. X        printf ("Mail comments to %s.\n", WIZARD);
  1023. X        fclose(fp);
  1024. X        cleanup(TRUE);
  1025. X        /*NOTREACHED*/
  1026. X        }
  1027. X    fclose (fp);
  1028. X    }
  1029. X}
  1030. X#endif
  1031. X
  1032. X/* */
  1033. X/************************************************************************
  1034. X/
  1035. X/ FUNCTION NAME: titlelist()
  1036. X/
  1037. X/ FUNCTION: print title page
  1038. X/
  1039. X/ AUTHOR: E. A. Estes, 12/4/85
  1040. X/
  1041. X/ ARGUMENTS: none
  1042. X/
  1043. X/ RETURN VALUE: none
  1044. X/
  1045. X/ MODULES CALLED: fread(), fseek(), fopen(), fgets(), wmove(), strcpy(), 
  1046. X/    fclose(), strlen(), waddstr(), sprintf(), wrefresh()
  1047. X/
  1048. X/ GLOBAL INPUTS: Lines, Other, *stdscr, Databuf[], Lastdead[], Motdfile[], 
  1049. X/    *Playersfp
  1050. X/
  1051. X/ GLOBAL OUTPUTS: Lines
  1052. X/
  1053. X/ DESCRIPTION:
  1054. X/    Print important information about game, players, etc.
  1055. X/
  1056. X/************************************************************************/
  1057. X
  1058. Xtitlelist()
  1059. X{
  1060. Xregister FILE    *fp;        /* used for opening various files */
  1061. Xbool    councilfound = FALSE;    /* set if we find a member of the council */
  1062. Xbool    kingfound = FALSE;    /* set if we find a king */
  1063. Xdouble    hiexp, nxtexp;        /* used for finding the two highest players */
  1064. Xdouble    hilvl, nxtlvl;        /* used for finding the two highest players */
  1065. Xchar    hiname[21], nxtname[21];/* used for finding the two highest players */
  1066. X
  1067. X    mvaddstr(0, 14, "W e l c o m e   t o   P h a n t a s i a (vers. 3.3.2)!");
  1068. X
  1069. X    /* print message of the day */
  1070. X    if ((fp = fopen(Motdfile, "r")) != NULL
  1071. X    && fgets(Databuf, SZ_DATABUF, fp) != NULL)
  1072. X    {
  1073. X    mvaddstr(2, 40 - strlen(Databuf) / 2, Databuf);
  1074. X    fclose(fp);
  1075. X    }
  1076. X
  1077. X    /* search for king */
  1078. X    fseek(Playersfp, 0L, 0);
  1079. X    while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  1080. X    if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
  1081. X        /* found the king */
  1082. X        {
  1083. X        sprintf(Databuf, "The present ruler is %s  Level:%.0f",
  1084. X        Other.p_name, Other.p_level);
  1085. X        mvaddstr(4, 40 - strlen(Databuf) / 2, Databuf);
  1086. X        kingfound = TRUE;
  1087. X        break;
  1088. X        }
  1089. X
  1090. X    if (!kingfound)
  1091. X    mvaddstr(4, 24, "There is no ruler at this time.");
  1092. X
  1093. X    /* search for valar */
  1094. X    fseek(Playersfp, 0L, 0);
  1095. X    while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  1096. X    if (Other.p_specialtype == SC_VALAR && Other.p_status != S_NOTUSED)
  1097. X        /* found the valar */
  1098. X        {
  1099. X        sprintf(Databuf, "The Valar is %s   Login:  %s", Other.p_name, Other.p_login);
  1100. X        mvaddstr(6, 40 - strlen(Databuf) / 2 , Databuf);
  1101. X        break;
  1102. X        }
  1103. X
  1104. X    /* search for council of the wise */
  1105. X    fseek(Playersfp, 0L, 0);
  1106. X    Lines = 10;
  1107. X    while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  1108. X    if (Other.p_specialtype == SC_COUNCIL && Other.p_status != S_NOTUSED)
  1109. X        /* found a member of the council */
  1110. X        {
  1111. X        if (!councilfound)
  1112. X        {
  1113. X        mvaddstr(8, 30, "Council of the Wise:");
  1114. X        councilfound = TRUE;
  1115. X        }
  1116. X
  1117. X        /* This assumes a finite (<=5) number of C.O.W.: */
  1118. X        sprintf(Databuf, "%s   Login:  %s", Other.p_name, Other.p_login);
  1119. X        mvaddstr(Lines++, 40 - strlen(Databuf) / 2, Databuf);
  1120. X        }
  1121. X
  1122. X    /* search for the two highest players */
  1123. X    nxtname[0] = hiname[0] = '\0';
  1124. X    hiexp = 0.0;
  1125. X    nxtlvl = hilvl = 0;
  1126. X
  1127. X    fseek(Playersfp, 0L, 0);
  1128. X    while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  1129. X    if (Other.p_experience > hiexp && Other.p_specialtype <= SC_KING && Other.p_status != S_NOTUSED)
  1130. X        /* highest found so far */
  1131. X        {
  1132. X        nxtexp = hiexp;
  1133. X        hiexp = Other.p_experience;
  1134. X        nxtlvl = hilvl;
  1135. X        hilvl = Other.p_level;
  1136. X        strcpy(nxtname, hiname);
  1137. X        strcpy(hiname, Other.p_name);
  1138. X        }
  1139. X    else if (Other.p_experience > nxtexp
  1140. X        && Other.p_specialtype <= SC_KING
  1141. X        && Other.p_status != S_NOTUSED)
  1142. X        /* next highest found so far */
  1143. X        {
  1144. X        nxtexp = Other.p_experience;
  1145. X        nxtlvl = Other.p_level;
  1146. X        strcpy(nxtname, Other.p_name);
  1147. X        }
  1148. X
  1149. X    mvaddstr(15, 28, "Highest characters are:");
  1150. X    sprintf(Databuf, "%s  Level:%.0f   and   %s  Level:%.0f",
  1151. X    hiname, hilvl, nxtname, nxtlvl);
  1152. X    mvaddstr(17, 40 - strlen(Databuf) / 2, Databuf);
  1153. X
  1154. X    /* print last to die */
  1155. X    if ((fp = fopen(Lastdead,"r")) != NULL
  1156. X    && fgets(Databuf, SZ_DATABUF, fp) != NULL)
  1157. X    {
  1158. X    mvaddstr(19, 25, "The last character to die was:");
  1159. X    mvaddstr(20, 40 - strlen(Databuf) / 2,Databuf);
  1160. X    fclose(fp);
  1161. X    }
  1162. X
  1163. X    refresh();
  1164. X}
  1165. X/* */
  1166. X/************************************************************************
  1167. X/
  1168. X/ FUNCTION NAME: recallplayer()
  1169. X/
  1170. X/ FUNCTION: find a character on file
  1171. X/
  1172. X/ AUTHOR: E. A. Estes, 12/4/85
  1173. X/
  1174. X/ ARGUMENTS: none
  1175. X/
  1176. X/ RETURN VALUE: none
  1177. X/
  1178. X/ MODULES CALLED: writerecord(), truncstring(), more(), death(), wmove(), 
  1179. X/    wclear(), strcmp(), printw(), cleanup(), waddstr(), findname(), mvprintw(), 
  1180. X/    getanswer(), getstring()
  1181. X/
  1182. X/ GLOBAL INPUTS: Player, *stdscr, Databuf[]
  1183. X/
  1184. X/ GLOBAL OUTPUTS: Echo, Player
  1185. X/
  1186. X/ DESCRIPTION:
  1187. X/    Search for a character of a certain name, and check password.
  1188. X/
  1189. X/************************************************************************/
  1190. X
  1191. Xlong
  1192. Xrecallplayer()
  1193. X{
  1194. Xlong    loc = 0L;        /* location in player file */
  1195. Xregister int    loop;        /* loop counter */
  1196. Xint    ch;            /* input */
  1197. X
  1198. X    clear();
  1199. X    mvprintw(10, 0, "What was your character's name ? ");
  1200. X    getstring(Databuf, SZ_NAME);
  1201. X    truncstring(Databuf);
  1202. X
  1203. X    if ((loc = findname(Databuf, &Player)) >= 0L)
  1204. X    /* found character */
  1205. X    {
  1206. X    Echo = FALSE;
  1207. X
  1208. X    for (loop = 0; loop < 2; ++loop)
  1209. X        {
  1210. X        /* prompt for password */
  1211. X        mvaddstr(11, 0, "Password ? ");
  1212. X        getstring(Databuf, SZ_PASSWORD);
  1213. X        if (strcmp(Databuf, Player.p_password) == 0)
  1214. X        /* password good */
  1215. X        {
  1216. X        Echo = TRUE;
  1217. X
  1218. X        if (Player.p_status != S_OFF)
  1219. X            /* player did not exit normally last time */
  1220. X            {
  1221. X            clear();
  1222. X            addstr("Your character did not exit normally last time.\n");
  1223. X            addstr("If you think you have good cause to have your character saved,\n");
  1224. X            printw("you may quit and mail your reason to '%s'.\n", WIZARD);
  1225. X            addstr("Otherwise, continuing spells certain death.\n");
  1226. X            addstr("Do you want to quit ? ");
  1227. X            ch = getanswer("YN", FALSE);
  1228. X            if (ch == 'Y')
  1229. X            {
  1230. X            Player.p_status = S_HUNGUP;
  1231. X            writerecord(&Player, loc);
  1232. X            cleanup(TRUE);
  1233. X            /*NOTREACHED*/
  1234. X            }
  1235. X            death("Stupidity");
  1236. X            /*NOTREACHED*/
  1237. X            }
  1238. X        return(loc);
  1239. X        }
  1240. X        else
  1241. X        mvaddstr(12, 0, "No good.\n");
  1242. X        }
  1243. X
  1244. X    Echo = TRUE;
  1245. X    }
  1246. X    else
  1247. X    mvaddstr(11, 0, "Not found.\n");
  1248. X
  1249. X    more(13);
  1250. X    return(-1L);
  1251. X}
  1252. X/* */
  1253. X/************************************************************************
  1254. X/
  1255. X/ FUNCTION NAME: neatstuff()
  1256. X/
  1257. X/ FUNCTION: do random stuff
  1258. X/
  1259. X/ AUTHOR: E. A. Estes, 3/3/86
  1260. X/
  1261. X/ ARGUMENTS: none
  1262. X/
  1263. X/ RETURN VALUE: none
  1264. X/
  1265. X/ MODULES CALLED: collecttaxes(), floor(), wmove(), random(), infloat(), 
  1266. X/    waddstr(), mvprintw(), getanswer()
  1267. X/
  1268. X/ GLOBAL INPUTS: Player, *stdscr, *Statptr
  1269. X/
  1270. X/ GLOBAL OUTPUTS: Player
  1271. X/
  1272. X/ DESCRIPTION:
  1273. X/    Handle gurus, medics, etc.
  1274. X/
  1275. X/************************************************************************/
  1276. X
  1277. Xneatstuff()
  1278. X{
  1279. Xdouble    temp;    /* for temporary calculations */
  1280. Xint    ch;    /* input */
  1281. X
  1282. X    switch ((int) ROLL(0.0, 100.0))
  1283. X    {
  1284. X    case 1:
  1285. X    case 2:
  1286. X        if (Player.p_poison > 0.0)
  1287. X        {
  1288. X        mvaddstr(4, 0, "You've found a medic!  How much will you offer to be cured ? ");
  1289. X        temp = floor(infloat());
  1290. X        if (temp < 0.0 || temp > Player.p_gold)
  1291. X            /* negative gold, or more than available */
  1292. X            {
  1293. X            mvaddstr(6, 0, "He was not amused, and made you worse.\n");
  1294. X            Player.p_poison += 1.0;
  1295. X            }
  1296. X        else if (random() / 2.0 > (temp + 1.0) / MAX(Player.p_gold, 1))
  1297. X            /* medic wants 1/2 of available gold */
  1298. X            mvaddstr(5, 0, "Sorry, he wasn't interested.\n");
  1299. X        else
  1300. X            {
  1301. X            mvaddstr(5, 0, "He accepted.");
  1302. X            Player.p_poison = MAX(0.0, Player.p_poison - 1.0);
  1303. X            Player.p_gold -= temp;
  1304. X            }
  1305. X        }
  1306. X        break;
  1307. X
  1308. X    case 3:
  1309. X        mvaddstr(4, 0, "You've been caught raping and pillaging!\n");
  1310. X        Player.p_experience += 4000.0;
  1311. X        Player.p_sin += 0.5;
  1312. X        break;
  1313. X
  1314. X    case 4:
  1315. X        temp = ROLL(10.0, 75.0);
  1316. X        mvprintw(4, 0, "You've found %.0f gold pieces, want them ? ", temp);
  1317. X        ch = getanswer("NY", FALSE);
  1318. X
  1319. X        if (ch == 'Y')
  1320. X        collecttaxes(temp, 0.0);
  1321. X        break;
  1322. X
  1323. X    case 5:
  1324. X        if (Player.p_sin > 1.0)
  1325. X        {
  1326. X        mvaddstr(4, 0, "You've found a Holy Orb!\n");
  1327. X        Player.p_sin -= 0.25;
  1328. X        }
  1329. X        break;
  1330. X
  1331. X    case 6:
  1332. X        if (Player.p_poison < 1.0)
  1333. X        {
  1334. X        mvaddstr(4, 0, "You've been hit with a plague!\n");
  1335. X        Player.p_poison += 1.0;
  1336. X        }
  1337. X        break;
  1338. X
  1339. X    case 7:
  1340. X        mvaddstr(4, 0, "You've found some holy water.\n");
  1341. X        ++Player.p_holywater;
  1342. X        break;
  1343. X
  1344. X    case 8:
  1345. X        mvaddstr(4, 0, "You've met a Guru. . .");
  1346. X        if (random() * Player.p_sin > 1.0)
  1347. X        addstr("You disgusted him with your sins!\n");
  1348. X        else if (Player.p_poison > 0.0)
  1349. X        {
  1350. X        addstr("He looked kindly upon you, and cured you.\n");
  1351. X        Player.p_poison = 0.0;
  1352. X        }
  1353. X        else
  1354. X        {
  1355. X        addstr("He rewarded you for your virtue.\n");
  1356. X        Player.p_mana += 50.0;
  1357. X        Player.p_shield += 2.0;
  1358. X        }
  1359. X        break;
  1360. X
  1361. X    case 9:
  1362. X        mvaddstr(4, 0, "You've found an amulet.\n");
  1363. X        ++Player.p_amulets;
  1364. X        break;
  1365. X
  1366. X    case 10:
  1367. X        if (Player.p_blindness)
  1368. X        {
  1369. X        mvaddstr(4, 0, "You've regained your sight!\n");
  1370. X        Player.p_blindness = FALSE;
  1371. X        }
  1372. X        break;
  1373. X
  1374. X    default:    /* deal with poison */
  1375. X        if (Player.p_poison > 0.0)
  1376. X        {
  1377. X        temp = Player.p_poison * Statptr->c_weakness
  1378. X            * Player.p_maxenergy / 600.0;
  1379. X        if (Player.p_energy > Player.p_maxenergy / 10.0
  1380. X            && temp + 5.0 < Player.p_energy)
  1381. X            Player.p_energy -= temp;
  1382. X        }
  1383. X        break;
  1384. X    }
  1385. X}
  1386. X/* */
  1387. X/************************************************************************
  1388. X/
  1389. X/ FUNCTION NAME: genchar()
  1390. X/
  1391. X/ FUNCTION: generate a random character
  1392. X/
  1393. X/ AUTHOR: E. A. Estes, 12/4/85
  1394. X/
  1395. X/ ARGUMENTS:
  1396. X/    int type - ASCII value of character type to generate
  1397. X/
  1398. X/ RETURN VALUE: none
  1399. X/
  1400. X/ MODULES CALLED: floor(), random()
  1401. X/
  1402. X/ GLOBAL INPUTS: Wizard, Player, Stattable[]
  1403. X/
  1404. X/ GLOBAL OUTPUTS: Player
  1405. X/
  1406. X/ DESCRIPTION:
  1407. X/    Use the lookup table for rolling stats.
  1408. X/
  1409. X/************************************************************************/
  1410. X
  1411. Xgenchar(type)
  1412. Xint    type;
  1413. X{
  1414. Xregister int    subscript;        /* used for subscripting into Stattable */
  1415. Xregister struct charstats    *statptr;/* for pointing into Stattable */
  1416. X
  1417. X    subscript = type - '1';
  1418. X
  1419. X    if (subscript < C_MAGIC || subscript > C_EXPER)
  1420. X    if (subscript != C_SUPER || !Wizard)
  1421. X        /* fighter is default */
  1422. X        subscript = C_FIGHTER;
  1423. X    
  1424. X    statptr = &Stattable[subscript];
  1425. X
  1426. X    Player.p_quickness =
  1427. X    ROLL(statptr->c_quickness.base, statptr->c_quickness.interval);
  1428. X    Player.p_strength =
  1429. X    ROLL(statptr->c_strength.base, statptr->c_strength.interval);
  1430. X    Player.p_mana =
  1431. X    ROLL(statptr->c_mana.base, statptr->c_mana.interval);
  1432. X    Player.p_maxenergy =
  1433. X    Player.p_energy =
  1434. X    ROLL(statptr->c_energy.base, statptr->c_energy.interval);
  1435. X    Player.p_brains =
  1436. X    ROLL(statptr->c_brains.base, statptr->c_brains.interval);
  1437. X    Player.p_magiclvl =
  1438. X    ROLL(statptr->c_magiclvl.base, statptr->c_magiclvl.interval);
  1439. X
  1440. X    Player.p_type = subscript;
  1441. X
  1442. X    if (Player.p_type == C_HALFLING)
  1443. X    /* give halfling some experience */
  1444. X    Player.p_experience = ROLL(600.0, 200.0);
  1445. X}
  1446. X/* */
  1447. X/************************************************************************
  1448. X/
  1449. X/ FUNCTION NAME: playinit()
  1450. X/
  1451. X/ FUNCTION: initialize for playing game
  1452. X/
  1453. X/ AUTHOR: E. A. Estes, 12/4/85
  1454. X/
  1455. X/ ARGUMENTS: none
  1456. X/
  1457. X/ RETURN VALUE: none
  1458. X/
  1459. X/ MODULES CALLED: signal(), wclear(), noecho(), crmode(), initscr(), 
  1460. X/    wrefresh()
  1461. X/
  1462. X/ GLOBAL INPUTS: *stdscr, ill_sig()
  1463. X/
  1464. X/ GLOBAL OUTPUTS: Windows
  1465. X/
  1466. X/ DESCRIPTION:
  1467. X/    Catch a bunch of signals, and turn on curses stuff.
  1468. X/
  1469. X/************************************************************************/
  1470. X
  1471. Xplayinit()
  1472. X{
  1473. X    /* catch/ingnore signals */
  1474. X
  1475. X#ifdef    BSD41
  1476. X    sigignore(SIGQUIT);
  1477. X    sigignore(SIGALRM);
  1478. X    sigignore(SIGTERM);
  1479. X    sigignore(SIGTSTP);
  1480. X    sigignore(SIGTTIN);
  1481. X    sigignore(SIGTTOU);
  1482. X    sighold(SIGINT);
  1483. X    sigset(SIGHUP, ill_sig);
  1484. X    sigset(SIGTRAP, ill_sig);
  1485. X    sigset(SIGIOT, ill_sig);
  1486. X    sigset(SIGEMT, ill_sig);
  1487. X    sigset(SIGFPE, ill_sig);
  1488. X    sigset(SIGBUS, ill_sig);
  1489. X    sigset(SIGSEGV, ill_sig);
  1490. X    sigset(SIGSYS, ill_sig);
  1491. X    sigset(SIGPIPE, ill_sig);
  1492. X#endif
  1493. X#ifdef    BSD42
  1494. X    signal(SIGQUIT, SIG_IGN);
  1495. X    signal(SIGALRM, SIG_IGN);
  1496. X    signal(SIGTERM, SIG_IGN);
  1497. X    signal(SIGTSTP, SIG_IGN);
  1498. X    signal(SIGTTIN, SIG_IGN);
  1499. X    signal(SIGTTOU, SIG_IGN);
  1500. X    signal(SIGINT, SIG_IGN);
  1501. X    signal(SIGHUP, ill_sig);
  1502. X    signal(SIGTRAP, ill_sig);
  1503. X    signal(SIGIOT, ill_sig);
  1504. X    signal(SIGEMT, ill_sig);
  1505. X    signal(SIGFPE, ill_sig);
  1506. X    signal(SIGBUS, ill_sig);
  1507. X    signal(SIGSEGV, ill_sig);
  1508. X    signal(SIGSYS, ill_sig);
  1509. X    signal(SIGPIPE, ill_sig);
  1510. X#endif
  1511. X#ifdef    SYS3
  1512. X    signal(SIGINT, SIG_IGN);
  1513. X    signal(SIGQUIT, SIG_IGN);
  1514. X    signal(SIGTERM, SIG_IGN);
  1515. X    signal(SIGALRM, SIG_IGN);
  1516. X    signal(SIGHUP, ill_sig);
  1517. X    signal(SIGTRAP, ill_sig);
  1518. X    signal(SIGIOT, ill_sig);
  1519. X    signal(SIGEMT, ill_sig);
  1520. X    signal(SIGFPE, ill_sig);
  1521. X    signal(SIGBUS, ill_sig);
  1522. X    signal(SIGSEGV, ill_sig);
  1523. X    signal(SIGSYS, ill_sig);
  1524. X    signal(SIGPIPE, ill_sig);
  1525. X#endif
  1526. X#ifdef    SYS5
  1527. X    signal(SIGINT, SIG_IGN);
  1528. X    signal(SIGQUIT, SIG_IGN);
  1529. X    signal(SIGTERM, SIG_IGN);
  1530. X    signal(SIGALRM, SIG_IGN);
  1531. X    signal(SIGHUP, ill_sig);
  1532. X    signal(SIGTRAP, ill_sig);
  1533. X    signal(SIGIOT, ill_sig);
  1534. X    signal(SIGEMT, ill_sig);
  1535. X    signal(SIGFPE, ill_sig);
  1536. X    signal(SIGBUS, ill_sig);
  1537. X    signal(SIGSEGV, ill_sig);
  1538. X    signal(SIGSYS, ill_sig);
  1539. X    signal(SIGPIPE, ill_sig);
  1540. X#endif
  1541. X
  1542. X    initscr();        /* turn on curses */
  1543. X    noecho();        /* do not echo input */
  1544. X    crmode();        /* do not process erase, kill */
  1545. X    clear();
  1546. X    refresh();
  1547. X    Windows = TRUE;    /* mark the state */
  1548. X}
  1549. X
  1550. X/* */
  1551. X/************************************************************************
  1552. X/
  1553. X/ FUNCTION NAME: cleanup()
  1554. X/
  1555. X/ FUNCTION: close some files, and maybe exit
  1556. X/
  1557. X/ AUTHOR: E. A. Estes, 12/4/85
  1558. X/
  1559. X/ ARGUMENTS:
  1560. X/    bool doexit - exit flag
  1561. X/
  1562. X/ RETURN VALUE: none
  1563. X/
  1564. X/ MODULES CALLED: exit(), wmove(), fclose(), endwin(), nocrmode(), wrefresh()
  1565. X/
  1566. X/ GLOBAL INPUTS: *Energyvoidfp, LINES, *stdscr, Windows, *Monstfp, 
  1567. X/    *Messagefp, *Playersfp
  1568. X/
  1569. X/ GLOBAL OUTPUTS: none
  1570. X/
  1571. X/ DESCRIPTION:
  1572. X/    Close all open files.  If we are "in curses" terminate curses.
  1573. X/    If 'doexit' is set, exit, otherwise return.
  1574. X/
  1575. X/************************************************************************/
  1576. X
  1577. Xcleanup(doexit)
  1578. Xbool    doexit;
  1579. X{
  1580. X    if (Windows)
  1581. X    {
  1582. X    move(LINES - 2, 0);
  1583. X    refresh();
  1584. X    nocrmode();
  1585. X    endwin();
  1586. X    }
  1587. X
  1588. X    fclose(Playersfp);
  1589. X    fclose(Monstfp);
  1590. X    fclose(Messagefp);
  1591. X    fclose(Energyvoidfp);
  1592. X
  1593. X    if (doexit)
  1594. X    exit(0);
  1595. X    /*NOTREACHED*/
  1596. X}
  1597. X/* */
  1598. X#ifdef    OK_TO_PLAY
  1599. X#include <sys/types.h>
  1600. X#include <utmp.h>   /* used for counting users on system */
  1601. X
  1602. X/************************************************************************
  1603. X/
  1604. X/ FUNCTION NAME: ok_to_play()
  1605. X/
  1606. X/ FUNCTION: indicate whether playing is allowed
  1607. X/
  1608. X/ AUTHOR: E. A. Estes, 12/4/85
  1609. X/
  1610. X/ ARGUMENTS: none
  1611. X/
  1612. X/ RETURN VALUE:
  1613. X/    FALSE if playing is not allowed
  1614. X/    TRUE if playing is allowed
  1615. X/
  1616. X/ MODULES CALLED: time(), fread(), fopen(), fclose(), localtime()
  1617. X/
  1618. X/ GLOBAL INPUTS: Wizard, Okcount
  1619. X/
  1620. X/ GLOBAL OUTPUTS: Okcount
  1621. X/
  1622. X/ DESCRIPTION: 
  1623. X/    This function is provided to allow one to restrict access to the game.
  1624. X/    Tailor this routine as appropriate.
  1625. X/    Return FALSE if playing is not allowed at this time.
  1626. X/
  1627. X/************************************************************************/
  1628. X
  1629. Xok_to_play()
  1630. X{
  1631. Xregister struct tm    *tp;    /* to get time of day */
  1632. Xregister int    numusers = 0;    /* number of users on system */
  1633. XFILE    *fp;            /* to open files */
  1634. Xlong    now;            /* present time */
  1635. Xstruct utmp    ubuf;        /* to read 'utmp' file */
  1636. X
  1637. X    if (Wizard)
  1638. X    /* wizard can always play */
  1639. X    return(TRUE);
  1640. X
  1641. X    if (Okcount >= 5)
  1642. X    Okcount = 0;
  1643. X    if (Okcount++ > 0)
  1644. X    /* only check every 5 times */
  1645. X    return(TRUE);
  1646. X
  1647. X    /* check time of day */
  1648. X    time(&now);
  1649. X    tp = localtime(&now);
  1650. X    if (((tp->tm_hour > 8 && tp->tm_hour < 12)        /* 8-noon */
  1651. X    || (tp->tm_hour > 12 && tp->tm_hour < 16))    /* 1-4 pm */
  1652. X    && (tp->tm_wday != 0 && tp->tm_wday != 6))    /* not a weekend */
  1653. X        return(FALSE);
  1654. X
  1655. X    /* check # of users */
  1656. X    if ((fp = fopen("/etc/utmp", "r")) != NULL)
  1657. X    {
  1658. X    while (fread((char *) &ubuf, sizeof(ubuf), 1, fp) == 1)
  1659. X#ifdef    SYS5
  1660. X        if (ubuf.ut_type == USER_PROCESS)
  1661. X#else
  1662. X        if (ubuf.ut_name[0] != '\0')
  1663. X#endif
  1664. X        ++numusers;
  1665. X    fclose(fp);
  1666. X
  1667. X    if (numusers > N_MAXUSERS)
  1668. X        return(FALSE);
  1669. X    }
  1670. X    return(TRUE);
  1671. X}
  1672. X#endif
  1673. !EOR!
  1674. echo x - include.h
  1675. sed 's/^X//' > include.h << '!EOR!'
  1676. X/*
  1677. X * include.h - includes all important files for Phantasia
  1678. X */
  1679. X
  1680. X#include <ctype.h>
  1681. X#include <curses.h>
  1682. X#include <math.h>
  1683. X#include <pwd.h>
  1684. X#include <setjmp.h>
  1685. X#include <signal.h>
  1686. X#include <time.h>
  1687. X
  1688. X#include "macros.h"
  1689. X#include "phantdefs.h"
  1690. X#include "phantstruct.h"
  1691. X#include "phantglobs.h"
  1692. !EOR!
  1693. echo x - phantstruct.h
  1694. sed 's/^X//' > phantstruct.h << '!EOR!'
  1695. X/*
  1696. X * phantstruct.h - structure definitions for Phantasia
  1697. X */
  1698. X
  1699. Xstruct    player            /* player statistics */
  1700. X    {
  1701. X    double    p_experience;    /* experience */
  1702. X    double    p_level;        /* level */
  1703. X    double    p_strength;    /* strength */
  1704. X    double    p_sword;    /* sword */
  1705. X    double    p_might;    /* effect strength */
  1706. X    double    p_energy;    /* energy */
  1707. X    double    p_maxenergy;    /* maximum energy */
  1708. X    double    p_shield;    /* shield */
  1709. X    double    p_quickness;    /* quickness */
  1710. X    double    p_quksilver;    /* quicksilver */
  1711. X    double    p_speed;    /* effective quickness */
  1712. X    double    p_magiclvl;    /* magic level */
  1713. X    double    p_mana;        /* mana */
  1714. X    double    p_brains;    /* brains */
  1715. X    double    p_poison;    /* poison */
  1716. X    double    p_gold;        /* gold */
  1717. X    double    p_gems;        /* gems */
  1718. X    double    p_sin;        /* sin */
  1719. X    double    p_x;            /* x coord */
  1720. X    double    p_y;            /* y coord */
  1721. X    double    p_1scratch,
  1722. X        p_2scratch;    /* variables used for decree, player battle */
  1723. X
  1724. X    struct
  1725. X    {
  1726. X    short    ring_type;    /* type of ring */
  1727. X    short    ring_duration;    /* duration of ring */
  1728. X    bool    ring_inuse;    /* ring in use flag */
  1729. X    }    p_ring;            /* ring stuff */
  1730. X
  1731. X    long    p_age;        /* age of player */
  1732. X
  1733. X    int        p_degenerated;    /* age/3000 last degenerated */
  1734. X
  1735. X    short    p_type;        /* character type */
  1736. X    short    p_specialtype;    /* special character type */
  1737. X    short    p_lives;    /* multiple lives for council, valar */
  1738. X    short    p_crowns;    /* crowns */
  1739. X    short    p_charms;    /* charms */
  1740. X    short    p_amulets;    /* amulets */
  1741. X    short    p_holywater;       /* holy water */
  1742. X    short    p_lastused;    /* day of year last used */
  1743. X    short    p_status;    /* playing, cloaked, etc. */
  1744. X    short    p_tampered;    /* decree'd, etc. flag */
  1745. X    short    p_istat;    /* used for inter-terminal battle */
  1746. X
  1747. X    bool    p_palantir;    /* palantir */
  1748. X    bool    p_blessing;    /* blessing */
  1749. X    bool    p_virgin;    /* virgin */
  1750. X    bool    p_blindness;    /* blindness */
  1751. X
  1752. X    char    p_name[SZ_NAME];    /* name */
  1753. X    char    p_password[SZ_PASSWORD];/* password */
  1754. X    char    p_login[SZ_LOGIN];    /* login */
  1755. X    };
  1756. X
  1757. Xstruct    monster            /* monster stats */
  1758. X    {
  1759. X    double    m_strength;    /* strength */
  1760. X    double    m_brains;    /* brains */
  1761. X    double    m_speed;    /* speed */
  1762. X    double    m_energy;    /* energy */
  1763. X    double    m_experience;    /* experience */
  1764. X    double    m_flock;        /* % chance of flocking */
  1765. X
  1766. X    double    m_o_strength;    /* original strength */
  1767. X    double    m_o_speed;    /* original speed */
  1768. X    double    m_maxspeed;    /* maximum speed */
  1769. X    double    m_o_energy;    /* original energy */
  1770. X    double    m_melee;    /* melee damage */
  1771. X    double    m_skirmish;    /* skirmish damage */
  1772. X
  1773. X    int        m_treasuretype;    /* treasure type */
  1774. X    int        m_type;            /* special type */
  1775. X
  1776. X    char    m_name[26];    /* name */
  1777. X    };
  1778. X
  1779. Xstruct    energyvoid         /* energy void */
  1780. X    {
  1781. X    double    ev_x;        /* x coordinate */
  1782. X    double    ev_y;        /* y coordinate */
  1783. X    bool    ev_active;    /* active or not */
  1784. X    };
  1785. X
  1786. Xstruct    scoreboard            /* scoreboard entry */
  1787. X    {
  1788. X    double    sb_level;        /* level of player */
  1789. X    char    sb_type[4];        /* character type of player */
  1790. X    char    sb_name[SZ_NAME];    /* name of player */
  1791. X    char    sb_login[SZ_LOGIN];    /* login of player */
  1792. X    };
  1793. X
  1794. Xstruct    charstats            /* character type statistics */
  1795. X    {
  1796. X    double    c_maxbrains;        /* max brains per level */
  1797. X    double    c_maxmana;        /* max mana per level */
  1798. X    double    c_weakness;        /* how strongly poison affects player */
  1799. X    double    c_goldtote;        /* how much gold char can carry */
  1800. X    int        c_ringduration;        /* bad ring duration */
  1801. X    struct
  1802. X    {
  1803. X    double    base;        /* base for roll */
  1804. X    double    interval;    /* interval for roll */
  1805. X    double    increase;    /* increment per level */
  1806. X    } c_quickness,        /* quickness */
  1807. X      c_strength,        /* strength */
  1808. X      c_mana,        /* mana */
  1809. X      c_energy,        /* energy level */
  1810. X      c_brains,        /* brains */
  1811. X      c_magiclvl;        /* magic level */
  1812. X    };
  1813. X
  1814. Xstruct menuitem                /* menu item for purchase */
  1815. X    {
  1816. X    char    *item;        /* menu item name */
  1817. X    double    cost;        /* cost of item */
  1818. X    };
  1819. !EOR!
  1820. echo x - map.c
  1821. sed 's/^X//' > map.c << '!EOR!'
  1822. X#define    minusminus    plusplus
  1823. X#define    minusplus    plusminus
  1824. X
  1825. Xmain()
  1826. X{
  1827. X    /* Set up */
  1828. X
  1829. X    openpl();
  1830. X    space(-1400, -1000, 1200, 1200);
  1831. X
  1832. X    /* Big box */
  1833. X
  1834. X    move(-1400, -1000);
  1835. X    cont(-1400, 1000);
  1836. X    cont(600, 1000);
  1837. X    cont(600, -1000);
  1838. X    cont(-1400, -1000);
  1839. X
  1840. X    /* Grid -- horizontal lines every 200 */
  1841. X
  1842. X    linemod("dotted");
  1843. X    line(600, -800, -1400, -800);
  1844. X    line(-1400, -600, 600, -600);
  1845. X    line(600, -400, -1400, -400);
  1846. X    line(-1400, -200, 600, -200);
  1847. X    linemod("solid");
  1848. X    line(600, 0, -1400, 0);
  1849. X    linemod("dotted");
  1850. X    line(-1400, 200, 600, 200);
  1851. X    line(600, 400, -1400, 400);
  1852. X    line(-1400, 600, 600, 600);
  1853. X    line(600, 800, -1400, 800);
  1854. X
  1855. X    /* Grid -- vertical lines every 200 */
  1856. X
  1857. X    line(-1200, 1000, -1200, -1000);
  1858. X    line(-1000, 1000, -1000, -1000);
  1859. X    line(-800, 1000, -800, -1000);
  1860. X    line(-600, 1000, -600, -1000);
  1861. X    linemod("solid");
  1862. X    line(-400, 1000, -400, -1000);
  1863. X    linemod("dotted");
  1864. X    line(-200, 1000, -200, -1000);
  1865. X    line(0, 1000, 0, -1000);
  1866. X    line(200, 1000, 200, -1000);
  1867. X    line(400, 1000, 400, -1000);
  1868. X
  1869. X    /* Circles radius +250 on "center" */
  1870. X
  1871. X    linemod("solid");
  1872. X    circle(-400, 0, 250);
  1873. X    circle(-400, 0, 500);
  1874. X    circle(-400, 0, 750);
  1875. X    circle(-400, 0, 1000);
  1876. X
  1877. X    /* A few labels */
  1878. X
  1879. X    move(-670, 1075);
  1880. X    label("- THE PHANTASIA UNIVERSE -");
  1881. X    line(-630, 1045, -115, 1045);
  1882. X    move(-360, 80);
  1883. X    label("Lorien");
  1884. X    move(-385, -100);
  1885. X    label("Ithilien");
  1886. X    move(-560, 80);
  1887. X    label("Rohan");
  1888. X    move(-580, -100);
  1889. X    label("Anorien");
  1890. X    plusplus("Rovanion", -250, 320);
  1891. X    plusplus("The Iron Hills", -100, 560);
  1892. X    plusplus("Rhun", 250, 570);
  1893. X    minusplus("Dunland", -700, 160);
  1894. X    minusplus("Eriador", -920, 300);
  1895. X    minusplus("The Northern Waste", -1240, 320);
  1896. X    minusminus("Gondor", -720, -180);
  1897. X    minusminus("South Gondor", -940, -270);
  1898. X    minusminus("Far Harad", -1100, -500);
  1899. X    plusminus("Mordor", -180, -300);
  1900. X    plusminus("Khand", 0, -500);
  1901. X    plusminus("Near Harad", 40, -780);
  1902. X    move(340, 900);
  1903. X    label("The Moors");
  1904. X    move(300, 840);
  1905. X    label("Adventurous");
  1906. X    move(340, -840);
  1907. X    label("The Moors");
  1908. X    move(300, -900);
  1909. X    label("Adventurous");
  1910. X    move(-1340, 900);
  1911. X    label("The Moors");
  1912. X    move(-1340, 840);
  1913. X    label("Adventurous");
  1914. X    move(-1340, -840);
  1915. X    label("The Moors");
  1916. X    move(-1340, -900);
  1917. X    label("Adventurous");
  1918. X    move(700, 1000);
  1919. X    label("OUTER CIRCLES:");
  1920. X    line(690, 970, 1000, 970);
  1921. X    move(700, 900);
  1922. X    label("> 9:  The Outer Waste");
  1923. X    move(700, 800);
  1924. X    label("> 20: The Dead Marshes");
  1925. X    move(700, 700);
  1926. X    label("> 35: Kennaquhair");
  1927. X    move(700, 600);
  1928. X    label("> 55: Morannon");
  1929. X    move(700, 300);
  1930. X    label("(0,0): The Lord's Chamber");
  1931. X
  1932. X    move(700, -400);
  1933. X    label("Grid squares are 100 x 100");
  1934. X    move(700, -800);
  1935. X    label("Created by Ted Estes");
  1936. X    move(700, -860);
  1937. X    label("Plotted by Chris Robertson");
  1938. X    move(700, -920);
  1939. X    label(" c  1985");
  1940. X    circle(723, -923, 20);
  1941. X
  1942. X    /* Close down */
  1943. X
  1944. X    move(-1380, 1180);
  1945. X    closepl();
  1946. X    exit(0);
  1947. X}
  1948. X
  1949. Xplusplus(s, x, y)    /* draw strings in plus plus quadrant */
  1950. Xchar    *s;
  1951. Xint    x, y;
  1952. X{
  1953. Xchar    s1[2];
  1954. X
  1955. X    while (*s)
  1956. X    {
  1957. X    move(x, y);
  1958. X    s1[0] = *s++;
  1959. X    s1[1] = '\0';
  1960. X    label(s1);
  1961. X    x += 25;
  1962. X    y -= 30;
  1963. X    }
  1964. X}
  1965. X
  1966. Xplusminus(s, x, y)    /* draw strings in plus minus quadrant */
  1967. Xchar    *s;
  1968. Xint    x, y;
  1969. X{
  1970. Xchar    s1[2];
  1971. X
  1972. X    while (*s)
  1973. X    {
  1974. X    move(x, y);
  1975. X    s1[0] = *s++;
  1976. X    s1[1] = '\0';
  1977. X    label(s1);
  1978. X    x += 25;
  1979. X    y += 30;
  1980. X    }
  1981. X}
  1982. !EOR!
  1983. echo x - monsters.asc
  1984. sed 's/^X//' > monsters.asc << '!EOR!'
  1985. XA Water Leaper          12      14      16      24      59      0       0       62
  1986. XA Leech                 4       19      29      30      66      0       0       73
  1987. XAn  Urisk               13      30      15      46      127     1       0       3
  1988. XShellycoat              28      21      18      63      226     2       0       0
  1989. XA Naiad                 21      62      27      58      378     2       0       11
  1990. XA Nixie                 22      58      28      108     604     3       0       6
  1991. XA Glaistig              21      106     25      127     1002    3       0       0
  1992. XA Mermaid               18      116     22      108     809     3       0       0
  1993. XA Merman                24      115     23      109     808     4       0       0
  1994. XA Siren                 22      128     31      89      915     4       0       24
  1995. XA Lamprey               14      67      33      156     1562    4       15      37
  1996. XA Kopoacinth            26      36      26      206     2006    5       0       20
  1997. XA Kelpie                61      25      24      223     4025    5       0       0
  1998. XAn Aspidchelone         114     104     19      898     10041   7       0       2
  1999. XAn Idiot                13      14      16      28      49      0       0       0
  2000. XSome Green Slime        1       5       45      100     57      0       0       26
  2001. XA Pixie                 11      29      23      26      64      0       0       32
  2002. XA Serpent               10      18      25      25      79      0       0       10
  2003. XA Cluricaun             12      27      20      30      81      0       14      5
  2004. XAn Imp                  22      30      14      40      92      0       0       1
  2005. XA Centipede             3       8       18      15      33      0       0       61
  2006. XA Beetle                2       11      21      26      44      0       0       48
  2007. XA Fir Darrig            18      22      17      35      107     0       14      1
  2008. XModnar                  15      23      20      40      101     7       2       12
  2009. XA Gnome                 7       45      26      23      111     0       0       21
  2010. XA Sprite                9       37      25      31      132     1       0       43
  2011. XA Mimic                 11      55      29      47      213     1       3       2
  2012. XA Kobold                13      10      14      21      121     1       12      68
  2013. XA Spider                6       11      28      28      124     1       0       57
  2014. XAn Uldra                14      37      21      32      93      1       0       6
  2015. XA Gnoll                 20      25      15      40      166     1       0       61
  2016. XA Bogie                 23      28      19      57      189     1       0       57
  2017. XA Fachan                9       40      15      45      139     1       14      10
  2018. XA Moron                 3       1       10      10      28      0       0       100
  2019. XAn Orc                  25      13      16      26      141     1       0       92
  2020. XA Ghillie Dhu           12      16      13      28      104     2       14      2
  2021. XA Bogle                 19      15      16      35      157     2       14      15
  2022. XA Shrieker              2       62      27      9       213     2       16      0
  2023. XA Carrion Crawler       12      20      20      65      142     2       0       42
  2024. XA Trow                  15      17      23      51      136     2       0       36
  2025. XA Warg                  20      10      17      45      152     2       0       88
  2026. XA Stirge                2       6       35      25      153     2       0       95
  2027. XA Crebain               5       11      31      31      82      2       0       81
  2028. XA Killmoulis            30      19      8       75      175     3       14      22
  2029. XA Hob-goblin            35      20      15      72      246     3       0       18
  2030. XA Unicorn               27      57      27      57      627     3       1       0
  2031. XA Fenoderee             16      6       21      65      222     3       0       42
  2032. XAn Ogre                 42      14      16      115     409     3       0       19
  2033. XA Dodo                  62      12      11      76      563     3       0       3
  2034. XA Hydra                 14      27      33      99      599     3       0       27
  2035. XA Hamadryad             23      47      26      62      426     3       0       12
  2036. XA Bwca                  21      17      19      55      387     3       14      1
  2037. XAn Owlbear              35      16      18      100     623     4       0       22
  2038. XBlack Annis             37      52      15      65      786     4       0       2
  2039. XA Jello Blob            100     25      7       264     1257    4       0       13
  2040. XA Jubjub Bird           45      23      12      114     1191    4       0       0
  2041. XA Wichtlein             13      40      25      61      800     4       0       8
  2042. XA Cocodrill             39      28      24      206     1438    4       0       38
  2043. XA Troll                 75      12      20      185     1013    4       24      29
  2044. XA Bonnacon              89      26      9       255     1661    4       17      14
  2045. XA Gargoyle              22      21      29      200     1753    5       0       7
  2046. XA Chaladrius            8       49      37      172     1929    5       0       20
  2047. XA Gwyllion              27      73      20      65      1888    5       0       4
  2048. XA Cinomulgus            23      2       10      199     263     5       0       18
  2049. XA Peridexion            26      32      24      98      1300    5       0       2
  2050. XSmeagol                 41      33      27      373     2487    5       18      0
  2051. XA Wraith                52      102     22      200     3112    5       25      13
  2052. XA Snotgurgle            143     19      26      525     4752    6       0       3
  2053. XA Phooka                42      63      21      300     4125    5       0       12
  2054. XA Vortex                101     30      31      500     6992    6       9       4
  2055. XShelob                  147     64      28      628     5003    7       13      0
  2056. XA Thaumaturgist         35      200     23      400     7628    6       7       0
  2057. XSmaug                   251     76      26      1022    9877    7       0       0
  2058. XA Cold-drake            301     102     24      1222    10888   7       0       0
  2059. XA Red Dragon            342     141     23      1299    11649   8       0       0
  2060. XScatha the Worm         406     208     20      1790    11999   8       0       0
  2061. XTiamat                  506     381     29      2000    13001   9       11      0
  2062. XA Bandersnatch          105     98      22      450     7981    6       0       3
  2063. XA Harpy                 103     49      24      263     7582    6       0       2
  2064. XA Tigris                182     38      17      809     7777    6       0       3
  2065. XA Gryphon               201     45      19      813     8888    7       0       1
  2066. XA Coblynau              205     46      18      585     8333    6       0       2
  2067. XA Chimaera              173     109     28      947     12006   7       0       0
  2068. XA Jack-in-Irons         222     36      12      1000    9119    7       0       0
  2069. XSaruman                 55      373     17      1500    17101   11      6       0
  2070. XA Balrog                500     100     25      705     8103    7       8       0
  2071. XArgus                   201     87      14      1500    10010   8       0       0
  2072. XA Titan                 302     1483    12      1625    11011   8       0       0
  2073. XCacus                   256     43      19      1750    12012   8       0       0
  2074. XBegion                  403     154     10      1875    13013   8       0       0
  2075. XGrendel                 197     262     23      2000    14014   8       0       0
  2076. XA Nazgul                250     251     26      1011    9988    12      10      9
  2077. XA Succubus              186     1049    27      2007    19984   9       19      0
  2078. XRed Cap                 143     50      35      1965    23456   9       0       0
  2079. XA Nuckelavee            300     75      20      2185    11111   8       0       0
  2080. XCerberus                236     96      29      2600    25862   9       20      0
  2081. XA Jabberwock            185     136     25      2265    23256   9       22      0
  2082. XUngoliant               399     2398    37      2784    27849   10      21      0
  2083. XLeanan-Sidhe            486     5432    46      3000    30004   9       5       0
  2084. XThe Dark Lord           9999    9999    31      19999   30005   13      4       0
  2085. !EOR!
  2086.  
  2087.  
  2088.